package com.mapler.mayzus.service;

import com.mapler.model.AdModel;
import com.mapler.model.SModel;
import com.mapler.model.UAModel;
import com.mapler.service.INotifier;
import com.mapler.service.MailRunner;
import com.mapler.utility.HttpHelper;
import com.mapler.utility.IConstant;
import com.mapler.utility.Util;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

/**
 *
 * @author none
 */
public class MayzusPostClick implements Runnable {

    private SModel sModel;
    private ArrayList<UAModel> uaModels;
    ArrayList<AdModel> addModels;
    private Random random;
    private HashMap<String, UAModel> usHashMap;
    private static Logger log = Logger.getLogger(MayzusPostClick.class);
    private INotifier iNotifier;

    public MayzusPostClick(INotifier iNotifier, SModel sModel, ArrayList<UAModel> uaModels, ArrayList<AdModel> addModels,
            HashMap<String, UAModel> usHashMap) {
        this.sModel = sModel;
        this.uaModels = uaModels;
        this.addModels = addModels;
        this.usHashMap = usHashMap;
        this.iNotifier = iNotifier;
    }

    public MayzusPostClick(SModel iModel) {
        this.sModel = iModel;
    }

    public Random getRandom() {
        if (random == null) {
            random = new Random();
        }
        return random;
    }

    public void setRandom(Random random) {
        this.random = random;
    }

    @Override
    public void run() {
        try {
            this.init();
        } catch (Throwable ex) {
            iNotifier.notify("Post:Run:: stopped for error: " + ex.getMessage());
            log.debug("Post:Run:: stopped causes " + ex);
        }
    }

    private void init() {
        if (sModel.isIsVPN()) {
            if (sModel.getProxy().isEmpty() || sModel.getName().isEmpty() || sModel.getPass().isEmpty()) {
                iNotifier.notify("Post:: Stop working proxy, username or password is empty");
                log.debug("Post:: Stop working proxy, username or password is empty");
                return;
            }
        }

        int postperip = 7;
        if (sModel.getPostPerIP() != null && !sModel.getPostPerIP().isEmpty()) {
            postperip = Integer.parseInt(sModel.getPostPerIP());
        }
        int postCount = 0;
        boolean isFirstPost = true;
        /* 0 initial data, 4 wrong username or password, 5 blocked form ngfx */
        String invalidworkgroup = "045";
        int postPerAcc = sModel.getPostPerAccout();
        for (int i = 1; i <= postPerAcc; i++) {
            if (sModel.isStopEngine()) {
                break;
            }
            for (UAModel uam : uaModels) {
                try {
                    if (sModel.isStopEngine()) {
                        break;
                    }
                    /* post will continue as of number of post below or equals to can post */
                    if (uam.getHavePost() != null && !uam.getHavePost().isEmpty()) {
                        int canPost = Integer.parseInt(uam.getCanPost());
                        int havePost = Integer.parseInt(uam.getHavePost());
                        if (canPost <= havePost) {
                            iNotifier.notify("Post:: Posting limit Exceeded " + uam.getEmail());
                            log.debug("Post:: Posting limit Exceeded " + uam.getEmail());
                            continue;
                        }
                    }

                    if (invalidworkgroup.contains(uam.getWorking())) {
                        continue;
                    }
                    if (sModel.isIsVPN()) {
                        postCount = postCount + 1;
                        if (isFirstPost || postperip < postCount) {
                            isFirstPost = false;
                            if (1 < postCount) {
                                iNotifier.notify("Post:: Going to disconnect for " + sModel.getProxy());
                                log.debug("Post:: Going to disconnect for " + sModel.getProxy());
                                boolean disconnect = Util.disConnect(sModel.getProxy(), sModel.getName(), sModel.getPass());
                                if (!disconnect) {
                                    iNotifier.notify("Post:: unable to disconnec VPN ");
                                    log.debug("Post:goVPN:: unable to disconnect VPN(no more further action) for " + sModel.getProxy());
                                    break;
                                } else {
                                    iNotifier.notify("Post:: disconnected from VPN ");
                                    log.debug("Post:: disconnected form VPN ");
                                }
                                postCount = 1;
                            }
                            iNotifier.notify("Post:: Going to connect VPN for " + sModel.getProxy());
                            boolean connect = Util.connect(sModel.getProxy(), sModel.getName(), sModel.getPass());
                            if (!connect) {
                                iNotifier.notify("Post:: unable to connect VPN for [" + sModel.getProxy() + "]. Try again.");
                                log.debug("Post:: unable to connect for " + uam.getProxy());
                                break;
                            }
                        }
                    }

                    iNotifier.notify("Post:: Goting to start post for " + uam.getEmail());
                    log.debug("Post:: Goting to start post for " + uam.getEmail());

                    this.doPost(uam);

                    //iNotifier.notify("Post:: Going to clean working directory ");
                    //Util.deleteFXTmpDirectory();

                    iNotifier.notify("Post:: Waiting 3 sec for before another post.");
                    Util.wait(3);

                } catch (Throwable ex) {
                    iNotifier.notify("Post::Critical error on post. No more work..." + ex.getMessage());
                    log.debug("Post::Critical error on post. No more work..." + ex);
                }
            }
        }
        iNotifier.notify("Post:: Finished work !!! ");
        log.debug("Post:: Finished work !!! ");
    }

    /*
     * 0 or null means initial save, 1 tried to signup and 2 for signup done, 3 signup done but manualy mail varification
     * 4 username and pass not valid, 5 means block user by ngfx.
     */
    private void doPost(UAModel uam) {
        WebDriver driver = null;
        try {
            driver = Util.createDriver(sModel, uam);
            if (driver == null) {
                iNotifier.notify("Post:: unable to init driver. driver is null");
                log.debug("Post:doPost:: driver is null. Unable to init driver");
                throw new Exception("Post:doPost:: driver is null. Unable to init driver");
            }

            iNotifier.notify("Post:: Working for account :" + " Email :" + uam.getEmail() + ", Please wait ...");

            driver.get("http://nigeria-forex.com/");
            iNotifier.notify("Going to login for [" + uam.getEmail() + "]");
            Util.wait(1);

            WebElement uName = driver.findElement(By.id("navbar_username"));
            uName.sendKeys(uam.getUsername());

            WebElement password = driver.findElement(By.id("navbar_password_hint"));
            password.sendKeys(uam.getPassword());

            List<WebElement> elements = driver.findElements(By.tagName("input"));
            for (WebElement elementLink : elements) {
                if ((elementLink.getAttribute("class") != null && elementLink.getAttribute("class").contains("loginbutton"))
                        && (elementLink.getAttribute("type") != null && elementLink.getAttribute("type").contains("submit"))) {
                    elementLink.submit();
                    break;
                }
            }
            Util.wait(2);
            /* Check successfully login or not */
            try {
                elements = driver.findElements(By.tagName("div"));
                for (WebElement elementLink : elements) {
                    if (elementLink.getAttribute("class") != null
                            && elementLink.getAttribute("class").contains("blockrow restore")) {
                        String loginMsg = elementLink.getText();
                        if (loginMsg.contains("You have entered an invalid username or password")) {
                            Util.updateNGFXWorking(sModel, uam.getId(), 4);
                            uam.setWorking("4");
                        }
                        break;
                    }
                }
            } catch (Throwable ex) {
                log.debug("Post:: Login successfully." + ex);
            }
            /*String pageofpage = "Page 1 of 2327";
             if (!pageofpage.contains("Page 1 of")) {
             //iNotifier.notify("Post:: Wrong page range selected. Going back to work for another one");
             //log.debug("Post:: Wrong page range selected. Going back to work for another one");
             }
             pageofpage = pageofpage.replace("Page", "").replace(" ", "");
             String[] pageRange = pageofpage.split("of");
             if (pageRange[0].isEmpty() || pageRange[1].isEmpty()) {
             //iNotifier.notify("Post:: Wrong page range selected. Going back to work for another one");
             //log.debug("Post:: Wrong page range selected. Going back to work for another one");
             }*/
            iNotifier.notify("Going to select topics for [" + uam.getEmail() + "]");
            int min = 1;
            int max = 30;
            List<WebElement> topics = new ArrayList<WebElement>();
            for (int i = 0;; i++) {
                int page = this.getRandom().nextInt(max - min + 1) + min;
                String link = "http://nigeria-forex.com/forumdisplay.php?5-General-Forex-Conversation/page@@@&order=desc";
                link = link.replace("@@@", "" + page);
                driver.get(link);
                Util.wait(2);

                elements = driver.findElements(By.tagName("div"));
                for (WebElement elementLink : elements) {
                    if (elementLink.getAttribute("class") != null
                            && elementLink.getAttribute("class").contains("rating5 nonsticky")) {
                        topics.add(elementLink);
                    }
                }
                if (topics.isEmpty()) {
                    iNotifier.notify("Post:: Topic not found. Going back to select another page");
                    log.debug("Post:: Topic not found. Going back to to select another page");
                    continue;
                }
                break;
            }
            if (topics.isEmpty()) {
                iNotifier.notify("Post:: Topics not found. Going back to select another account");
                log.debug("Post:: Topics not found. Going back to to select another account");
                return;
            }
            int index = this.getRandom().nextInt(topics.size());
            WebElement topic = topics.get(index);

            boolean isTopic = false;
            elements = topic.findElements(By.tagName("a"));
            for (WebElement elementLink : elements) {
                if ((elementLink.getAttribute("class") != null && elementLink.getAttribute("class").contains("title"))
                        && (elementLink.getAttribute("id") != null && elementLink.getAttribute("id").contains("thread_title_"))) {
                    elementLink.click();
                    isTopic = true;
                    break;
                }
            }
            if (!isTopic) {
                iNotifier.notify("Best topic not found for [" + uam.getEmail() + "]" + "Going back to work for another account");
                log.debug("Best topic not found for [" + uam.getEmail() + "]" + "Going back to work for another account");
                return;
            }

            iNotifier.notify("Going to select posting information for [" + uam.getEmail() + "]");
            /* Click on page if multipel page comments found */
            boolean isFirstPage = true;
            try {
                WebElement element = driver.findElement(By.id("postpagestats_above"));
                if (element != null) {
                    String pageofpage = element.getText();
                    if (pageofpage.contains("Results 1 to")) {
                        pageofpage = pageofpage.replace("Results", "").replace("to", ":").replace("of", ":").replaceAll(" ", "");
                        String[] pageRange = pageofpage.split(":");
                        if (pageRange.length == 3) {
                            if (!pageRange[0].isEmpty() && !pageRange[2].isEmpty()) {
                                min = Integer.parseInt(pageRange[0]);
                                max = Integer.parseInt(pageRange[2]);
                                if (27 < max) {
                                    max = 27;
                                }
                                int page = this.getRandom().nextInt(max - min + 1) + min;
                                String url = driver.getCurrentUrl();
                                url = url + "/page" + page;
                                if (1 < page) {
                                    isFirstPage = false;
                                }
                                driver.get(url);
                                Util.wait(2);
                            }
                        }
                    }
                }
            } catch (Throwable ex) {
                log.debug("Error on seleceting page from multipel page commects. " + ex.getMessage());
            }

            /* Collect all post information from selected page */
            List<WebElement> postinfos = new ArrayList<WebElement>();
            elements = driver.findElements(By.tagName("div"));
            for (WebElement elementLink : elements) {
                if (elementLink.getAttribute("class") != null
                        && elementLink.getAttribute("class").contains("postdetails")) {
                    if (isFirstPage) {
                        isFirstPage = false;
                        continue;
                    }
                    postinfos.add(elementLink);
                }
            }

            /* Get random post information within the post information list */
            String postText = "";
            for (WebElement elementLink : postinfos) {
                index = this.getRandom().nextInt(postinfos.size());
                WebElement postinfo = postinfos.get(index);

                /* If Banned link then go back and select another topics */
                boolean isBLink = false;
                elements = postinfo.findElements(By.tagName("span"));
                for (WebElement bLink : elements) {
                    if (bLink.getAttribute("class") != null
                            && bLink.getAttribute("class").contains("usertitle")
                            && bLink.getText().contains("Banned")) {
                        isBLink = true;
                    }
                }
                if (isBLink) {
                    iNotifier.notify("Banned found. Going back to select another postig info for [" + uam.getEmail() + "]");
                    log.debug("Banned found. Going back to select another postig info for [" + uam.getEmail() + "]");
                    continue;
                }

                /* If post has comments then  ignore and select another topics */
                boolean isComments = false;
                elements = postinfo.findElements(By.tagName("div"));
                for (WebElement cLink : elements) {
                    if (cLink.getAttribute("class") != null
                            && cLink.getAttribute("class").contains("quote_container")) {
                        isComments = true;
                    }
                }
                if (isComments) {
                    iNotifier.notify("Comments found. Going back to select another postig info for [" + uam.getEmail() + "]");
                    log.debug("Comments found. Going back to select another postig info for [" + uam.getEmail() + "]");
                    continue;
                }

                elements = postinfo.findElements(By.tagName("blockquote"));
                for (WebElement pLink : elements) {
                    if (pLink.getAttribute("class") != null
                            && pLink.getAttribute("class").contains("postcontent restore")) {
                        postText = pLink.getText();
                        break;
                    }
                }
                if (postText.isEmpty() || postText.split(" ").length < 50) {
                    continue;
                }
                break;
            }

            if (postText.isEmpty()) {
                iNotifier.notify("Post:: Valid posting text not found. Going back to work for another one");
                log.debug("Post:: Valid posting text not found. Going back to work for another one");
                return;
            }

            /* check modarator block posting or not */
            if (!sModel.isIgnoreBannedCheck()) {
                iNotifier.notify("Going to check banned user for [" + uam.getEmail() + "]");
                WebElement permissionDiv = driver.findElement(By.id("forumrules"));
                List<WebElement> permissions = permissionDiv.findElements(By.tagName("li"));
                for (WebElement pLink : permissions) {
                    String pText = pLink.getText();
                    if (pText.contains("may not") && pText.contains("post new threads")) {
                        Util.updateNGFXWorking(sModel, uam.getId(), 5);
                        iNotifier.notify("Banned user found for [" + uam.getEmail() + "]. Going to work for another account");
                        log.debug("Banned user found for [" + uam.getEmail() + "]. Going to work for another account");
                        uam.setWorking("5");
                        return;
                    }
                }
            }
            String postingURI = driver.getCurrentUrl();

            /* Going spin posting information */
            iNotifier.notify("Going to spinning informatin for [" + uam.getEmail() + "]");
            String spninningText = "";
            if (sModel.getSpinner().equals("bestfreespinner.com")) {
                spninningText = this.spinFromBestfreespinner(driver, postText);
            } else if (sModel.getSpinner().equals("freeonlinearticlespinner.com")) {
                spninningText = this.spinFromFreeonlinearticlespinner(driver, postText);
            }

            if (spninningText.isEmpty()) {
                iNotifier.notify("Problem on spinning for [" + uam.getEmail() + "]. Going back to work on another account.");
                return;
            }

            driver.get(postingURI);
            Util.wait(2);

            iNotifier.notify("Spinning done going to posting informatin for [" + uam.getEmail() + "]");
            WebElement element = driver.findElement(By.id("vB_Editor_QR_textarea"));
            element.sendKeys(spninningText);

            element = driver.findElement(By.id("qr_submit"));
            element.submit();

            if (uam.getHavePost() == null || uam.getHavePost().isEmpty()) {
                uam.setHavePost("1");
            } else {
                int havepost = Integer.parseInt(uam.getHavePost()) + 1;
                uam.setHavePost("" + havepost);
            }
            this.updatePosting(uam.getId());
        } catch (Throwable ex) {
            iNotifier.notify("Post: Stopped for error: " + ex.getMessage());
            log.debug("Post:doPost:: Stopped causes..." + ex);
            ex.printStackTrace();
        } finally {
            if (driver != null) {
                driver.close();
            }
        }
    }
    //bestfreespinner.com, freeonlinearticlespinner.com

    private String spinFromBestfreespinner(WebDriver driver, String postText) {
        try {
            driver.get("http://www.bestfreespinner.com");
            Util.wait(1);
            WebElement element = driver.findElement(By.id("spintext"));
            element.sendKeys(postText);

            /* Choice spninning options */
            element = driver.findElement(By.id("frequency"));
            element.sendKeys("Best Spin every other word/phrase");

            Util.wait(1);
            element = driver.findElement(By.id("button"));
            element.submit();

            Util.wait(2);
            element = driver.findElement(By.id("spuntext"));
            String spninningText = element.getText();
            return spninningText;
        } catch (Throwable ex) {
            ex.printStackTrace();
            log.debug("Error on spinning post information ." + ex);
            iNotifier.notify("Error on spinning post information ." + ex);
        }
        return "";
    }

    //bestfreespinner.com, freeonlinearticlespinner.com
    private String spinFromFreeonlinearticlespinner(WebDriver driver, String postText) {
        try {
            driver.get("http://www.freeonlinearticlespinner.com");
            Util.wait(1);

            WebElement elementSpunText = driver.findElement(By.id("spunText"));
            elementSpunText.sendKeys(postText);
            WebElement elementJS = (WebElement) ((JavascriptExecutor) driver)
                    .executeScript("document.getElementById('spunText').select();");

            List<WebElement> elements = driver.findElements(By.tagName("a"));
            for (WebElement elementLink : elements) {
                if ((elementLink.getAttribute("onclick") != null && elementLink.getAttribute("onclick").contains("createSpunText"))) {
                    elementLink.click();
                    break;
                }
            }
            int tryin = 7;
            String spunText = "";
            for (int i = 0;; i++) {
                Util.wait(3);
                spunText = elementSpunText.getAttribute("value");
                if (!spunText.isEmpty()) {
                    break;
                }
                if (i == tryin) {
                    break;
                }
            }

            WebElement element = driver.findElement(By.id("spinText"));
            element.sendKeys(spunText);

            element = driver.findElement(By.id("button_silver"));
            element.click();

            String spninningText = "";
            for (int i = 0;; i++) {
                try {
                    Util.wait(2);
                    driver.findElement(By.id("d_clip_button1")).click();
                    Util.wait(1);
                    WebElement articleEle = driver.findElement(By.id("articleText"));
                    spninningText = articleEle.getAttribute("value");
                    if (!spninningText.isEmpty()) {
                        break;
                    }
                    if (i == tryin) {
                        break;
                    }
                } catch (Throwable ex) {
                    log.debug("Error on spinning post information ." + ex);
                    iNotifier.notify("Error on spinning post information ." + ex);
                }

            }
            return spninningText;
        } catch (Throwable ex) {
            ex.printStackTrace();
            log.debug("Error on spinning post information ." + ex);
            iNotifier.notify("Error on spinning post information ." + ex);
        }
        return "";
    }

    private void updatePosting(String id) {
        /* update account information */
        try {
            StringBuilder request = new StringBuilder();
            request.append("<Request>");
            request.append("<id>").append(id).append("</id>");
            request.append("<username>").append(sModel.getUsername()).append("</username>");
            request.append("<password>").append(sModel.getPassword()).append("</password>");
            request.append("<posting>").append("1").append("</posting>");
            request.append("</Request>");

            String req = URLEncoder.encode(request.toString(), "UTF-8");
            String uri = "http://" + IConstant.HOSTNAME + "/index.php?r=ngfxaccount/updatePost";
            String param = "request=" + req;
            String response = HttpHelper.post(new URL(uri), param);

            Document document = DocumentHelper.parseText(response);
            String msg = document.valueOf("Response/message");
            iNotifier.notify("Post:: " + msg);
        } catch (Exception ex) {
            iNotifier.notify("Post:: problem on updating post information " + ex.getMessage());
            log.debug("Post:: problem on updating post information " + ex.getMessage());
        }
    }

    public static void main(String s[]) {
        SModel sModel = new SModel();
        sModel.setDriver("FF");
        sModel.setUsername("mithun");
        sModel.setPassword("mithun");
        sModel.setWebMail(false);
        MayzusPostClick click = new MayzusPostClick(sModel);
        UAModel model = new UAModel();
        model.setEmail("idmdtje@clirobot.com");
        model.setEmailPassword("gmail@@7");
        model.setUsername("omar10");
        model.setPassword("dhaka1215");
        model.setId("1483");

        //click.doPost(model);
        
        //click.doIT();
        //WebDriver driver = Util.createDriver(sModel);
        //driver.get("https://motivosity.hipchat.com/");    
    }

    private void doIT() {
        SModel sModel = new SModel();
        sModel.setDriver("FF");
        sModel.setLink("http://nigeria-forex.com/forum.php?referrerid=27246");
        sModel.setUseFWlink("0");
        sModel.setUsername("mithun");
        sModel.setPassword("mithun");
        MayzusPostClick click = new MayzusPostClick(sModel);
        UAModel model = new UAModel();
        model.setEmail("skyroproject8@gmail.com");
        model.setEmailPassword("mn142536");
        model.setUsername("prantoor");
        model.setPassword("pass123");
        model.setId("22");
        MailRunner mailRunner = new MailRunner(iNotifier, sModel, model);
        mailRunner.checkNGFXEmail(null);
    }
}